package edu.kufpg.armatus.console;
import android.graphics.Color;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.style.BackgroundColorSpan;
import android.text.style.ForegroundColorSpan;
import com.google.common.base.Objects;
import edu.kufpg.armatus.data.CommandResponse;
import edu.kufpg.armatus.util.ParcelUtils;
import edu.kufpg.armatus.util.StringUtils;
import java.util.ArrayList;
/**
* Contains values that describe an entry in {@link ConsoleListView}. This class
* is primarily used for populating {@link android.view.View Views} in {@link
* ConsoleEntryAdapter}.
*/
public class ConsoleEntry implements Parcelable {
/**
* The unique entry number used to identify this entry. Entry numbers begin
* at 0 (although the first entry in the console may not be 0 since the number
* of entries could exceed the {@link ConsoleActivity#CONSOLE_ENTRY_LIMIT
* CONSOLE_ENTRY_LIMIT}).
*/
private final int mEntryNum;
private final int mAst;
private String mUserInput;
private CommandResponse mCommandResponse;
private String mErrorResponse;
private CharSequence mShortContents;
private ArrayList<CharSequence> mContentLines;
public ConsoleEntry(int entryNum, int ast, String userInput) {
this(entryNum, ast, userInput, null, null);
}
public ConsoleEntry(int entryNum, int ast, String userInput, CommandResponse commandResponse) {
this(entryNum, ast, userInput, commandResponse, null);
}
public ConsoleEntry(int entryNum, int ast, String userInput, String errorResponse) {
this(entryNum, ast, userInput, null, errorResponse);
}
protected ConsoleEntry(int entryNum, int ast, String userInput, CommandResponse commandResponse, String errorResponse) {
this(entryNum, ast, userInput, commandResponse, errorResponse, buildShortContents(userInput, commandResponse, errorResponse));
}
protected ConsoleEntry(int entryNum, int ast, String userInput, CommandResponse commandResponse,
String errorResponse, CharSequence shortContents) {
mEntryNum = entryNum;
mAst = ast;
mUserInput = userInput;
mCommandResponse = commandResponse;
mErrorResponse = errorResponse;
mShortContents = shortContents;
mContentLines = makeContentLines(getFullContents());
}
protected ConsoleEntry(int entryNum, int ast, String userInput, CommandResponse commandResponse,
String errorResponse, CharSequence shortContents, ArrayList<CharSequence> contentLines) {
mEntryNum = entryNum;
mAst = ast;
mUserInput = userInput;
mCommandResponse = commandResponse;
mErrorResponse = errorResponse;
mShortContents = shortContents;
mContentLines = contentLines;
}
/**
* Constructs a new instance with the specified {@code ConsoleEntry}'s number
* and contents.
* @param entry the {@code ConsoleEntry} to copy.
*/
public ConsoleEntry(ConsoleEntry entry) {
this(entry.getEntryNum(), entry.getAst(), entry.getUserInput(), entry.getCommandResponse(),
entry.getErrorResponse(), entry.getShortContents(), entry.getContentLines());
}
public int getAst() {
return mAst;
}
/**
* Returns the entry's unique number.
* @return the number used to identify this entry.
*/
public int getEntryNum() {
return mEntryNum;
}
public String getUserInput() {
return mUserInput;
}
public CommandResponse getCommandResponse() {
return mCommandResponse;
}
public String getErrorResponse() {
return mErrorResponse;
}
/**
* Returns this entry's contents without the {@code hermit<ast> }prefix.
* @return the unadorned entry contents.
*/
public CharSequence getShortContents() {
return mShortContents;
}
public ArrayList<CharSequence> getContentLines() {
return mContentLines;
}
/**
* Returns this entry's contents including the {@code hermit<ast> }prefix.
* @return the entry contents, including the prefix.
*/
public CharSequence getFullContents() {
return getFullContentsPrefix().append(getShortContents());
}
public SpannableStringBuilder getFullContentsPrefix() {
SpannableStringBuilder prefix = new SpannableStringBuilder(StringUtils.NBSP);
if (mAst != HermitClient.NO_TOKEN) {
prefix = prefix.append("hermit<").append(String.valueOf(mAst)).append('>');
} else {
prefix = prefix.append("armatus");
}
prefix = prefix.append(StringUtils.NBSP);
prefix.setSpan(new BackgroundColorSpan(Color.DKGRAY), 0, prefix.length(), 0);
prefix.setSpan(new ForegroundColorSpan(Color.WHITE), 0, prefix.length(), 0);
return prefix.append(StringUtils.NBSP);
}
public void appendCommandResponse(CommandResponse commandResponse) {
mCommandResponse = commandResponse;
mShortContents = buildShortContents(mUserInput, mCommandResponse, mErrorResponse);
mContentLines = makeContentLines(getFullContents());
}
public void appendErrorResponse(String errorResponse) {
mErrorResponse = errorResponse;
mShortContents = buildShortContents(mUserInput, mCommandResponse, mErrorResponse);
mContentLines = makeContentLines(getFullContents());
}
void setUserInput(String userInput) {
mUserInput = userInput;
mShortContents = buildShortContents(mUserInput, mCommandResponse, mErrorResponse);
mContentLines = makeContentLines(getFullContents());
}
private static ArrayList<CharSequence> makeContentLines(CharSequence contents) {
ArrayList<CharSequence> contentLines = new ArrayList<CharSequence>();
int lineStart = 0;
int length = contents.length();
for (int i = 0; i < length; i++) {
if (contents.charAt(i) == '\n') {
contentLines.add(contents.subSequence(lineStart, i));
lineStart = i + 1;
}
}
contentLines.add(contents.subSequence(lineStart, length));
return contentLines;
}
private static CharSequence buildShortContents(String userInput, CommandResponse commandResponse, String errorResponse) {
SpannableStringBuilder builder = new SpannableStringBuilder();
if (userInput != null) {
builder.append(userInput).append("\n");
}
if (commandResponse != null) {
if (commandResponse.hasGlyphs()) {
builder.append(commandResponse.getGlyphText()).append("\n");
}
if (commandResponse.hasMessage()) {
builder.append(commandResponse.getMessage()).append("\n");
}
}
if (errorResponse != null) {
builder.append(errorResponse).append("\n");
}
if (builder.length() > 0) {
builder = builder.delete(builder.length()-1, builder.length());
}
return builder;
}
@Override
public boolean equals(Object o) {
if (o instanceof ConsoleEntry) {
ConsoleEntry ce = (ConsoleEntry) o;
return mAst == ce.getAst()
&& mEntryNum == ce.getEntryNum()
&& mUserInput.equals(ce.getUserInput())
&& mErrorResponse.equals(ce.getErrorResponse())
&& mCommandResponse.equals(ce.getCommandResponse());
} else {
return false;
}
}
@Override
public int hashCode() {
return Objects.hashCode(mAst, mEntryNum, mUserInput, mCommandResponse, mErrorResponse);
}
public static final Parcelable.Creator<ConsoleEntry> CREATOR
= new Parcelable.Creator<ConsoleEntry>() {
@Override
public ConsoleEntry createFromParcel(Parcel in) {
int entryNum = in.readInt();
int ast = in.readInt();
String userInput = in.readString();
CommandResponse commandResponse = in.readParcelable(CommandResponse.class.getClassLoader());
String errorResponse = in.readString();
CharSequence shortContents = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
ArrayList<CharSequence> contentLines = ParcelUtils.readArrayList(in);
return new ConsoleEntry(entryNum, ast, userInput, commandResponse, errorResponse, shortContents, contentLines);
}
@Override
public ConsoleEntry[] newArray(int size) {
return new ConsoleEntry[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mEntryNum);
dest.writeInt(mAst);
dest.writeString(mUserInput);
dest.writeParcelable(mCommandResponse, flags);
dest.writeString(mErrorResponse);
TextUtils.writeToParcel(mShortContents, dest, flags);
ParcelUtils.writeCollection(dest, mContentLines);
}
}